package top.guochenchen.mydb.backend.tm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import top.guochenchen.mydb.backend.utils.Panic;
import top.guochenchen.mydb.common.Error;

public interface TransactionManager {
    long begin();//开启一个新的事务
    void commit(long xid);//提交一个事务，将事务状态设为已提交
    void abort(long xid);//回滚一个事务，将事务状态设为已回滚
    boolean isActive(long xid);//检查一个事务是否处于活跃状态
    boolean isCommitted(long xid);//检查一个事务是否已提交
    boolean isAborted(long xid);//检查一个事务是否已回滚
    void close();//关闭事务管理器

    //作用：从零创建新的 XID 文件并初始化 TM。
    //参数：path：XID 文件路径
    //返回：TransactionManagerImpl：事务管理器
    public static TransactionManagerImpl create(String path) {
        File f = new File(path+TransactionManagerImpl.XID_SUFFIX);//创建XID文件
        try {
            if(!f.createNewFile()) {//尝试创建文件，如果文件已存在，则抛出异常
                Panic.panic(Error.FileExistsException);//文件已存在则panic
            }
        } catch (Exception e) {
            Panic.panic(e);//创建文件失败则panic
        }
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);//文件不可读写则panic
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(f, "rw");//以读写方式打开文件
            fc = raf.getChannel();//获取I/O通道
        } catch (FileNotFoundException e) {
           Panic.panic(e);//打开文件失败则panic
        }

        // 写空XID文件头
        ByteBuffer buf = ByteBuffer.wrap(new byte[TransactionManagerImpl.LEN_XID_HEADER_LENGTH]);
        try {
            fc.position(0);//将通道定位到文件头
            fc.write(buf);//写入8字节全0的头部
        } catch (IOException e) {
            Panic.panic(e);//写入失败则panic
        }
        
        return new TransactionManagerImpl(raf, fc);
    }

    //作用：打开已存在的 XID 文件并初始化 TM。
    //参数：path：XID 文件路径
    //返回：TransactionManagerImpl：事务管理器
    public static TransactionManagerImpl open(String path) {
        File f = new File(path+TransactionManagerImpl.XID_SUFFIX);//创建XID文件
        if(!f.exists()) {
            Panic.panic(Error.FileNotExistsException);//文件不存在则panic
        }
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);//文件不可读写则panic
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(f, "rw");//以读写方式打开文件
            fc = raf.getChannel();//获取I/O通道
        } catch (FileNotFoundException e) {
           Panic.panic(e);//打开文件失败则panic
        }

        return new TransactionManagerImpl(raf, fc);//返回事务管理器实例
    }
}
